import { useCallback, DragEvent, useRef, Dispatch, SetStateAction, useMemo } from 'react';
import {
  ReactFlow,
  Controls,
  Background,
  useReactFlow,
} from '@xyflow/react';
import type {
  Node,
  Edge,
  OnNodesChange,
  OnEdgesChange,
  OnConnect,
  NodeTypes,
} from '@xyflow/react';
import { useTranslation } from 'react-i18next';

import './WorkflowEditor.css';
import CustomNode from './CustomNode';

let id = 2;
const getId = () => `${id++}`;

interface WorkflowEditorProps {
  nodes: Node[];
  edges: Edge[];
  setNodes: Dispatch<SetStateAction<Node<any, string | undefined>[]>>;
  onNodesChange: OnNodesChange;
  onEdgesChange: OnEdgesChange;
  onConnect: OnConnect;
}

function WorkflowEditor({ nodes, edges, setNodes, onNodesChange, onEdgesChange, onConnect }: WorkflowEditorProps) {
  const reactFlowWrapper = useRef<HTMLDivElement>(null);
  const { screenToFlowPosition } = useReactFlow();
  const { t } = useTranslation();

  const nodeTypes: NodeTypes = useMemo(() => ({
    read_csv: CustomNode,
    inspect_data: CustomNode,
    select_columns: CustomNode,
    random_forest_train: CustomNode,
  }), []);

  const onDragOver = useCallback((event: DragEvent) => {
    event.preventDefault();
    event.dataTransfer.dropEffect = 'move';
  }, []);

  const onDrop = useCallback(
    (event: DragEvent) => {
      event.preventDefault();
      const type = event.dataTransfer.getData('application/reactflow');
      if (typeof type === 'undefined' || !type) return;

      const position = screenToFlowPosition({ x: event.clientX, y: event.clientY });
      
      const translationKey = `nodes.${type}`;
      const initialLabel = t(translationKey);

      const newNode: Node = {
        id: getId(),
        type,
        position,
        data: { tKey: translationKey, label: initialLabel },
      };

      setNodes((nds) => nds.concat(newNode));
    },
    [screenToFlowPosition, setNodes, t]
  );

  return (
    <div className="workflow-editor" ref={reactFlowWrapper} onDrop={onDrop} onDragOver={onDragOver}>
      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        onConnect={onConnect}
        nodeTypes={nodeTypes}
        deleteKeyCode={['Backspace', 'Delete']}
        fitView
      >
        <Controls />
        <Background />
      </ReactFlow>
    </div>
  );
}

export default WorkflowEditor;